// Copyright (c) 2022 Presto Labs Pte. Ltd.
// Author: qiang

#pragma once

#include <functional>
#include <memory>
#include <string>
#include <unordered_map>

#include "coin2/exchange/base/market/market_exchange_api.h"
#include "coin2/exchange/base/order/external.h"
#include "coin2/exchange/base/order/message_bus.h"
#include "coin2/exchange/base/order/processor.h"
#include "coin2/exchange/base/symbology/product_holder_manager.h"
#include "coin2/exchange/factory/order/parser.h"

namespace coin2::exchange::base::order {

class SyncTradeClient {
 public:
  using OrderConnectionConfig = coin2::exchange::order::OrderConnectionConfig;
  using NativeHttpAsioDriver = base::api_base::NativeHttpAsioDriver;
  using LiveAsyncExecutor = base::api_base::LiveAsyncExecutor;
  using Callback = std::function<void(const RawMessageProto&)>;
  using BaseParser = coin2::exchange::base::order::BaseParser;
  using ProductHolderManager = coin2::exchange::base::symbology::ProductHolderManager;
  using AsioHttpContextList = std::list<std::shared_ptr<AsioHttpContext>>;

  SyncTradeClient(const coin2::exchange::order::OrderSystemConfig& osc_config);

  void QueryTransferHistories(
      const int64_t start_timestamp,
      const int64_t end_timestamp,
      std::vector<coin::proto::CurrencyTransferElement>* transfer_out);  // time: ns

 private:
  void TransferExecutor(
      std::shared_ptr<AsioHttpContext> context,
      std::vector<coin::proto::CurrencyTransferElement>* transfer_out);

  bool InitGdax();
  void Init();

  AsioHttpContextList
  GetRequestList(const int64_t start_timestamp, const int64_t end_timestamp, std::string mea);

 private:
  std::unique_ptr<NativePrivateClient> client_;
  std::unique_ptr<BaseParser> parser_;
  MarketExchangeApi mea_;
  coin2::exchange::order::OrderSystemConfig osc_config_;
  MessageBus bus_;
  bool is_initialized = false;

  int64_t last_init_timestamp_;
};
}  // namespace coin2::exchange::base::order
